#ifndef xpack_utils_bits_indexer
#define xpack_utils_bits_indexer
#pragma push_macro("xuser")
#undef  xuser
#define xuser mixc::utils_bits_indexer::inc
#include"define/base_type.hpp"
#include"macro/xexport.hpp"
#include"macro/xstruct.hpp"
#pragma pop_macro("xuser")

namespace mixc::utils_bits_indexer::origin{
    template<uxx length_v>
    requires(length_v <= 16 and length_v > 0)
    xstruct(
        xname(bits_indexer),
        xprif(m_bits, u64)
    )
    private:
        static constexpr auto bits_per_item = 4;
        static constexpr auto default_value = 0x0123456789abcdefULL >> (64 - length_v * bits_per_item);
    public:
        /**
         * @brief 
         * 构造位索引
         * 位索引每个元素 4bit，一共 16 个元素
         * 借用位组的移动来代替数组元素的移动
         * @note 该位组最多只能表示 16 个元素的数组
         */
        constexpr bits_indexer(u64 value = default_value):
            m_bits(value){
        }

        /**
         * @brief 
         * 在指定索引插入元素
         * @param index 插入元素的索引
         * @param value 插入的值
         * @return uxx 如果位组存满了，该值表示的是最后一个元素的值
         */
        uxx insert(uxx index, uxx value){
            index      *= (bits_per_item);
            u64 msk     = (u64(-1) << index);
            u64 low     = (m_bits & ~msk);
            u64 hig     = (m_bits &  msk) << bits_per_item;
            u64 out     = (m_bits >> (length_v * bits_per_item - bits_per_item)) & 0xf;
            u64 ins     = (u64(value) << index);
            m_bits      = (low | hig | ins);
            return out;
        }

        /**
         * @brief 
         * 移除指定索引的元素
         * @param index 索引
         * @return uxx 被移除元素的值
         */
        uxx remove(uxx index){
            index      *= (bits_per_item);
            u64 msk     = (u64(-1) << index);
            u64 low     = (m_bits & ~msk);
            u64 hig     = (m_bits & (msk << bits_per_item)) >> bits_per_item;
            u64 out     = (m_bits >> index) & 0xf;
            m_bits      = (low | hig);
            return out;
        }

        /**
         * @brief 
         * 获取指定索引元素的值
         * @param index 索引
         * @return uxx 指定索引元素的值
         */
        uxx get(uxx index) const {
            index      *= bits_per_item;
            return (m_bits >> index) & 0xf;
        }

        /**
         * @brief 
         * 设置指定索引元素的值
         * @param index 索引
         * @param value 值
         */
        void set(uxx index, uxx value){
            index      *=  (bits_per_item);
            m_bits     &= ~(u64(0xf) << index);
            m_bits     |=  (u64(value) << index);
        }

        void clear(){
            m_bits      = default_value;
        }

        uxx length() const {
            return length_v;
        }

        operator u64 () const {
            return m_bits;
        }

        the_t & operator= (u64 value){
            m_bits      = value;
            return xthe;
        }
    $
}

#endif

xexport_space(mixc::utils_bits_indexer::origin)
